#pragma once
#include"util.hpp"
#include"Config .hpp"
#include<unordered_map>
#include<pthread.h>

//该类是用于对于用户上传数据管理
namespace cloud
{
    class  BackupInfo
    {
        public:
        bool _pack_flag;
        size_t _fsize;
        time_t _mtime;
        time_t _atime;
        std::string _real_path;
        std::string _pack_path;
        std::string _url;
        public:
        BackupInfo(){}
        BackupInfo(const std::string real_path)
        {
            FileUtil fl(real_path);
            if(fl.Exists()==false)
            {
                std::cout<<"File Not Exists";
                //return false;
                return;
            }
            Config* config=Config::GetInstance();
            _pack_flag=false;
            _fsize=fl.FileSize();
            _mtime=fl.LastMtime();
            _atime=fl.LastAtime();
            _real_path=real_path;
            _pack_path=config->GetPackDir()+fl.FileName()+config->GetPackFileSuffix();
            _url=config->GetDownloadPrefix()+fl.FileName();
            


        }
        
        
        

    };

    class DataManager
    {

        public:
        DataManager()
        {
            _backup_file=Config::GetInstance()->GetBackupFile();
            
            pthread_rwlock_init(&_rwlock,nullptr);
            InitLoad();
        }
        ~DataManager()
        {
            pthread_rwlock_destroy(&_rwlock);
        }
        bool Insert(BackupInfo&info)
        {
            pthread_rwlock_wrlock(&_rwlock);
            
            _table[info._url]=info;
            
            
            pthread_rwlock_unlock(&_rwlock);
            Storage();
            
            return true;
        }
        bool Update(BackupInfo&info)
        {
            pthread_rwlock_wrlock(&_rwlock);
            _table[info._url]=info;
            
            pthread_rwlock_unlock(&_rwlock);
            Storage();
            return true;
        }
        bool GetOneByUrl(const std::string &url,BackupInfo*info)
        {
            pthread_rwlock_wrlock(&_rwlock);
            auto it= _table.find(url);//哈希的意义就在这
            if(it==_table.end())
            {
                pthread_rwlock_unlock(&_rwlock);//天哪这里忘记解锁就麻烦了
                return false;
            }
            *info=it->second;
            pthread_rwlock_unlock(&_rwlock);
            return true;
        }
        bool GetOneByRealPath(const std::string &realpath, BackupInfo *info) {
				pthread_rwlock_wrlock(&_rwlock);
				auto it = _table.begin();
				for (; it != _table.end(); ++it){
					if (it->second._real_path == realpath) {
						*info = it->second;
						pthread_rwlock_unlock(&_rwlock);
						return true;
					}
				}
				pthread_rwlock_unlock(&_rwlock);
				return false;
			}
        bool GetAll(std::vector<BackupInfo>*arr)
        {
            pthread_rwlock_wrlock(&_rwlock);
            // for(auto&[x,y]:_table)
            // {
            //     arr->push_back(y);
            // }
            auto it = _table.begin();
				for (; it != _table.end(); ++it){
					arr->push_back(it->second);
				}
            pthread_rwlock_unlock(&_rwlock);
            return true;
            
        }
        bool Storage()
        {
            std::vector<BackupInfo> arr;
            GetAll(&arr);
            Json::Value root;
            for(auto&a:arr)
            {
                Json::Value item;
                item["pack_flag"] = a._pack_flag;
				item["fsize"] = (Json::Int64)a._fsize;
				item["atime"] = (Json::Int64)a._atime;
				item["mtime"] = (Json::Int64)a._mtime;
				item["real_path"] = a._real_path;
				item["pack_path"] = a._pack_path;
				item["url"] = a._url;
                root.append(item);
            }
            std::string data;
            JsonFile::Serialize(root,&data);
            FileUtil fl(_backup_file);
            //std::cout<<"#############################"<<data<<std::endl;
            fl.SetContent(data);
            return true;

        }
        bool InitLoad()
        {
            FileUtil fl(_backup_file);
            if(fl.Exists()==false)return true;
            std:: string data;
            fl.GetContent(&data);
            Json::Value root;
            JsonFile::UnSerialize(data,&root);
            for(int i=0;i<root.size();i++)
            {
                BackupInfo info;
                info._atime=root[i]["pack_flag"].asBool();
                info._fsize = root[i]["fsize"].asInt64();
				info._atime = root[i]["atime"].asInt64();
				info._mtime = root[i]["mtime"].asInt64();
				info._pack_path = root[i]["pack_path"].asString();
				info._real_path = root[i]["real_path"].asString();
				info._url = root[i]["url"].asString();
				Insert(info);
            }
            return true;
        }
        private:
        std::string _backup_file; 
        std::unordered_map<std::string,BackupInfo> _table;
        pthread_rwlock_t _rwlock;

    };
    
}